package com.fll.codeworld.doc;

import com.alibaba.druid.util.StringUtils;
import com.spire.doc.*;
import com.spire.doc.collections.*;
import com.spire.doc.documents.*;
import com.spire.doc.fields.ShapeObject;
import com.spire.doc.fields.TextRange;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Encoder;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.*;
import java.util.Map;
import java.util.UUID;

/**
 * spireDoc操作工具类
 *
 * @author fff
 * @date 2021/11/17
 */
@Component
public class FtlToWordUtil {

    private static final String TOC = "附件1：任务流程汇总跟踪表";
    private static Logger logger = LoggerFactory.getLogger(FtlToWordUtil.class);
    private static final String filePath = "d:\\";
    private static final String str = "一二三四五六七八";
    /**
     * 初始化配置文件
     *
     * @param folderPath 生成word的文件夹路径
     * @return Configuration
     */
    private static Configuration initConfiguration(String folderPath) {
        Configuration configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
        try {
            //这里对应模板的物理路径
            configuration.setDirectoryForTemplateLoading(new File(folderPath));
        } catch (IOException e) {
            logger.error("初始化configuration失败，路径不存在：{}", folderPath);
            e.printStackTrace();
        }
        return configuration;
    }

    /**
     * 根据ftl模板生成word文件
     *
     * @param dataMap      word中需要展示的动态数据，用map集合来保存
     * @param templateName word模板名称，例如：word.ftl
     */
    public static String createWord(Map dataMap, String templateName) {
        System.out.println("创建word文件！");
        String newPDFPath = "/word/" + UUID.randomUUID() + ".doc";
        try {
            //创建配置实例
            Configuration configuration = initConfiguration(filePath + "/wordFtl/");
            Template template = configuration.getTemplate(templateName);
            //输出文件  输出文档路径及名称
            File outFile = new File(filePath + newPDFPath);
            if (!outFile.getParentFile().exists()) {
                outFile.getParentFile().mkdirs();
            }
            //将模板和数据模型合并生成文件
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));
            //生成文件
            template.process(dataMap, out);
            //关闭流
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return newPDFPath;
    }


    /**
     * 图片转base64的字符串
     *
     * @param imageAbsolutePath 图片路径
     * @return String
     */
    public static String imageToBase64Str(String imageAbsolutePath) {
        System.out.println("========================" + imageAbsolutePath);
        InputStream is = null;
        byte[] data = null;
        try {
            is = new FileInputStream(imageAbsolutePath);
            data = new byte[is.available()];
            is.read(data);
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);
    }

    /**
     * 添加书签
     *
     * @param path
     */
    public static void insertBookmark(String path, String itemName, int i) {
        Document doc = new Document(path);
        TextSelection textSelection = doc.findString(itemName, false, false);
        TextRange range = textSelection.getAsOneRange();
        Paragraph para = range.getOwnerParagraph();
        int index = para.getChildObjects().indexOf(range);
        //添加书签
        BookmarkStart start = new BookmarkStart(doc, itemName + i);
        BookmarkEnd end = new BookmarkEnd(doc, itemName + i);
        para.getChildObjects().insert(index + 1, start);
        para.getChildObjects().insert(index + 2, end);
        //保存文档
        doc.saveToFile(path, FileFormat.Docx_2013);
        doc.dispose();
    }

    /**
     * 导出word文档，响应到请求端
     *
     * @param tempName，要使用的模板
     * @param docName，导出文档名称
     * @param dataMap，模板中变量数据
     * @param resp,HttpServletResponse
     */
    public static boolean exportDoc(String folderPath, String tempName, String docName, Map<?, ?> dataMap, HttpServletResponse resp) {
        boolean status = false;
        Configuration configuration = initConfiguration(folderPath);
        ServletOutputStream sos = null;
        InputStream fin = null;
        if (resp != null) {
            resp.reset();
        }
        Template t = null;
        try {
            // tempName.ftl为要装载的模板
            t = configuration.getTemplate(tempName);
            t.setEncoding("utf-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 输出文档路径及名称 ,以临时文件的形式导出服务器，再进行下载
        String name = folderPath + "temp" + (int) (Math.random() * 100000) + ".doc";
        File outFile = new File(name);

        Writer out = null;
        try {
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"));
            status = true;
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        try {
            t.process(dataMap, out);
            out.close();
        } catch (TemplateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            fin = new FileInputStream(outFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        // 文档下载
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("application/msword");
        try {
            docName = new String(docName.getBytes("UTF-8"), "ISO-8859-1");
        } catch (UnsupportedEncodingException e1) {
            e1.printStackTrace();
        }
        resp.setHeader("Content-disposition", "attachment;filename=" + docName + ".doc");
        try {
            sos = resp.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 缓冲区
        byte[] buffer = new byte[512];
        int bytesToRead = -1;
        // 通过循环将读入的Word文件的内容输出到浏览器中
        try {
            while ((bytesToRead = fin.read(buffer)) != -1) {
                sos.write(buffer, 0, bytesToRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fin != null) {
                try {
                    fin.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (sos != null) {
                try {
                    sos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outFile != null) {
                outFile.delete(); // 删除临时文件
            }
        }
        return status;
    }

    /**
     * spire生成目录
     *
     * @param folderPath 生成word的文件夹路径
     * @return Configuration
     */
    public static String getPageCount(String folderPath) {
        Document doc = new Document(folderPath);
        //通过域代码添加目录表(7:根据模板推算得知)
        if (doc.getSections().get(0).getParagraphs().getCount() >= 7) {
            doc.getSections().get(0).getParagraphs().get(7).appendTOC(1, 3);
        }
        doc.updateTableOfContents();
        //保存文档
        String pathString2 = folderPath.substring(0, folderPath.indexOf("."));
        String newPath = pathString2 + ".docx";
        doc.saveToFile(newPath);
        //删除doc文件
        deleteFile(folderPath);
        //去除警告
        removeSpireWarning(newPath);
        return newPath;
    }

    /**
     * 删除文件
     *
     * @param file_path
     */
    public static boolean deleteFile(String file_path) {
        boolean flag = true;
        try {
            File file = new File(file_path);
            if (!file.exists()) {
                return false;
            }
            if (file.isFile()) {
                file.delete();
            }
        } catch (Exception e) {
            System.out.println("删除文件失败");
            return false;
        }
        return flag;
    }

    /**
     * 插入页码(重新)
     *
     * @param document
     */
    public static Document HeaderFooterForOddAndEvenPages(Document document) {
        //获取第一个节中的页脚
        HeaderFooter footer = document.getSections().get(1).getHeadersFooters().getFooter();
        //添加段落到页脚
        Paragraph footerParagraph = footer.addParagraph();
        //添加页脚域样式
        ParagraphStyle footerStyle = (ParagraphStyle) Style.createBuiltinStyle(BuiltinStyle.Footer, document);
        footerStyle.setName("footerStyle");
        footerStyle.getCharacterFormat().setFontName("仿宋_GB2312");
        footerStyle.getCharacterFormat().setFontSize(9);
        document.getStyles().add(footerStyle);
        footerParagraph.applyStyle("footerStyle");
        //添加文字、页码域和总页数域到段落
        footerParagraph.appendText("第");
        footerParagraph.appendField("page number", FieldType.Field_Page);
        footerParagraph.appendText("页 共");
        footerParagraph.appendField("number of pages", FieldType.Field_Num_Pages);
        footerParagraph.appendText("页");
        //初始化总页数域
//        footerParagraph.appendField("number of pages", FieldType.Field_Page);
        footerParagraph.appendText(document.getPageCount() + "页");
        //设置从第一页开始计数(页码重新计数)
        document.getSections().get(1).getPageSetup().setRestartPageNumbering(true);
        document.getSections().get(1).getPageSetup().setPageStartingNumber(1);
        //将段落居中
        footerParagraph.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
        //判断文档是否含多个节
        if (document.getSections().getCount() > 1) {
            //遍历除第一节以外的其他节
            for (int i = 1; i < document.getSections().getCount(); i++) {
                //在当前节重新开始编页码
                document.getSections().get(i).getPageSetup().setRestartPageNumbering(true);
                //从1开始编页码
                document.getSections().get(i).getPageSetup().setPageStartingNumber(1);
            }
        }
        return document;
    }

    /**
     * @author wanghaonan
     * @description 修改目录文本样式
     * @date 2021-06-28
     */
    private static void updateTocText(Document doc) {
        for (Section sec : (Iterable<? extends Section>) doc.getSections()) {
            //遍历body下面所有对象
            for (DocumentObject obj : (Iterable<? extends DocumentObject>) sec.getBody().getChildObjects()) {
                if (obj instanceof Paragraph) {
                    Paragraph para = (Paragraph) obj;
                    //查找含有TOC域的段落
                    for (DocumentObject tr : (Iterable<? extends DocumentObject>) para.getChildObjects()) {
                        if (tr.getDocumentObjectType() == DocumentObjectType.TOC || tr.getDocumentObjectType() == DocumentObjectType.Field) {
                            changeText(para);
                            break;
                        }
                    }
                }
            }
        }
    }

    private static void changeText(Paragraph para) {
        for (DocumentObject tr : (Iterable<? extends DocumentObject>) para.getChildObjects()) {
            if (tr.getDocumentObjectType() == DocumentObjectType.Text_Range) {
                TextRange textRange = (TextRange) tr;
                if (!StringUtils.equals(textRange.getText(), TOC)) {
                    textRange.setText("★" + textRange.getText());
                }
                break;
            }
        }
    }

    /**
     * 设置word部分内容样式
     *
     * @param doc
     */
    private static void setWordStyle(Document doc) {
        //获取所有节
        SectionCollection sections = doc.getSections();
        for (Section section : (Iterable<? extends Section>) sections) {
            //获取所有段落
            ParagraphCollection paragraphs = section.getParagraphs();
            for (Paragraph paragraph : (Iterable<? extends Paragraph>) paragraphs) {
                //获取段落下的内容
                DocumentObjectCollection childObjects = paragraph.getChildObjects();
                for (DocumentObject obj : (Iterable<? extends DocumentObject>) childObjects) {
                    //添加判断
                    if (obj.getDocumentObjectType() == DocumentObjectType.TOC || obj.getDocumentObjectType() == DocumentObjectType.Field || obj.getDocumentObjectType() == DocumentObjectType.Shape) {
                        //设置目行距为固定值29磅
                        paragraph.getFormat().setLineSpacingRule(LineSpacingRule.Exactly);
                        paragraph.getFormat().setLineSpacing(29);
                    }
                    //修改线条样式
                    if (obj.getDocumentObjectType() == DocumentObjectType.Shape) {
                        ShapeObject rectangle = (ShapeObject) paragraph.getChildObjects().get(0);
                        rectangle.setFillColor(Color.red);
                        rectangle.setStrokeColor(Color.red);
                        break;
                    }
                }
            }
        }
    }

    /**
     * 取出spire.java警告
     *
     * @param path
     */
    public static void removeSpireWarning(String path) {
        try {
            //重新读取生成的文档
            InputStream is = new FileInputStream(path);
            XWPFDocument document = new XWPFDocument(is);
            //以上Spire.Doc 生成的文件会自带警告信息，这里来删除Spire.Doc 的警告
            document.removeBodyElement(0);
            //输出word内容文件流，新输出路径位置
            OutputStream os = new FileOutputStream(path);
            document.write(os);
            System.out.println("去除警告");
            System.out.println("生成docx文档成功！");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据书签复制word
     *
     * @param copyPath   被复制word
     * @param targetPath 目标word
     */
    public static void copyWordByBookMark(String copyPath, String targetPath) {
        Document copyDoc = new Document(copyPath);
        Document targetDoc = new Document(targetPath);
        //激活目标文档书签
        BookmarksNavigator bookmarksNavigator = new BookmarksNavigator(targetDoc);
        bookmarksNavigator.moveToBookmark("mark1");
        TextBodyPart textBodyPart = bookmarksNavigator.getBookmarkContent();
        //获取目标文档的"节"
        SectionCollection sectionCollection = copyDoc.getSections();
        //遍历所有节,复制所有内容到书签位置
        for (int i = 0; i < sectionCollection.getCount(); i++) {
            DocumentObjectCollection objs = sectionCollection.get(i).getBody().getChildObjects();
            for (int j = 0; j < objs.getCount(); j++) {
                DocumentObject obj = objs.get(j);
                if (obj.getDocumentObjectType() == DocumentObjectType.Paragraph || obj.getDocumentObjectType() == DocumentObjectType.Table) {
                    textBodyPart.getBodyItems().add(obj.deepClone());
                }
            }
        }
        //替换书签内容
        bookmarksNavigator.replaceBookmarkContent(textBodyPart);
        targetDoc.saveToFile(targetPath);
        targetDoc.dispose();
    }

    /**
     * 复制全部文档
     *
     * @param copyPath
     * @param targetPath
     */
    public static void copyWord(String copyPath, String targetPath) {
        //加载文档1
        Document doc1 = new Document(copyPath);
        //加载文档2
        Document doc2 = new Document(targetPath);
        //遍历文档1中的所有子对象
        for (int i = 0; i < doc1.getSections().getCount(); i++) {
            Section section = doc1.getSections().get(i);
            for (int j = 0; j < section.getBody().getChildObjects().getCount(); j++) {
                Object object = section.getBody().getChildObjects().get(j);
                //复制文档1中的正文内容添加到文档2
                doc2.getSections().get(0).getBody().getChildObjects().add(((DocumentObject) object).deepClone());
            }
            doc2.getSections().add(section.deepClone());
        }
        //保存文档2
        doc2.saveToFile(targetPath, FileFormat.Docx_2013);
        doc2.dispose();
    }


    /**
     * word复制段落
     *
     * @param copyPath
     * @param targetPath
     */
    public static void copyParagraph(String copyPath, String targetPath) {
        //加载文档1
        Document doc1 = new Document(copyPath);
        //获取文档1中的第三段
        Section section1 = doc1.getSections().get(0);
        Paragraph paragraph = section1.getParagraphs().get(2);
        //加载文档2，获取section
        Document doc2 = new Document(targetPath);
        Section section2 = doc2.getSections().get(0);
        //复制文档1中段落，添加到文档2
        Paragraph newParagraph = (Paragraph) paragraph.deepClone();
        section2.getParagraphs().add(newParagraph);
        //保存文档2
        doc2.saveToFile(targetPath, FileFormat.Docx_2013);
        doc2.dispose();
    }

    public static void main(String[] args) throws IOException {
        Document doc = new Document("C:\\Users\\fll\\Desktop\\日常工作\\测试4444444.docx");
        ParagraphStyle style = new ParagraphStyle(doc);
        style.setName(UUID.randomUUID().toString());
        style.getCharacterFormat().setFontName("宋体");
        style.getCharacterFormat().setFontSize(16);
        doc.getStyles().add(style);
        SectionCollection sections = doc.getSections();
        int sectionsCount = sections.getCount();
        if (sections.getCount() >= 2) {
            for (int i = 1; i < sectionsCount; i++) {
                //获取所有段落
                if (i == 1) {
                    //设置表格样式
                    TableCollection tables = sections.get(i).getTables();
                    int count = tables.getCount();
                    for (int k = 0; k < count; k++) {
                        Table table = tables.get(k);
                        table.applyStyle(DefaultTableStyle.Table_Normal);
                        table.getTableFormat().getBorders().getRight().setBorderType(BorderStyle.Hairline);
                        table.getTableFormat().getBorders().getRight().setLineWidth(5.0F);
                        RowCollection rows = tables.get(k).getRows();
                        int rowCount = rows.getCount();
                        for (int h = 0; h < rowCount; h++) {
                            TableRow row = rows.get(h);
                            CellCollection cells = row.getCells();
                            int cellsCount = cells.getCount();
                            for (int j = 0; j < cellsCount; j++) {
                                //获取单元格
                                TableCell cell = cells.get(j);
                                ParagraphCollection paragraphs = cell.getParagraphs();
                                int paragraphsCount = paragraphs.getCount();
                                System.out.println("paragraphsCount:"+paragraphsCount);
                                for (int m = 0; m < paragraphsCount; m++) {
                                    paragraphs.get(m).applyStyle(style.getName());
                                }
                                //cell.getCellFormat().clearFormatting();//清除单元格格式
                                //cell.getParagraphs().removeAt(0);//删除单元格中的段落
                            }
                        }
                    }
                }
                /**
                 * 设置正文样式
                 */
                ParagraphCollection paragraphs = sections.get(i).getParagraphs();
                for (Paragraph paragraph : (Iterable<? extends Paragraph>) paragraphs) {
                    //获取段落下的内容
                    DocumentObjectCollection childObjects = paragraph.getChildObjects();
                    for (DocumentObject obj : (Iterable<? extends DocumentObject>) childObjects) {
                        //设置目行距为固定值29磅
                        paragraph.getFormat().clearFormatting();
                        paragraph.getFormat().setLineSpacingRule(LineSpacingRule.Exactly);
                        paragraph.getFormat().setLineSpacing(28);
                        if (obj.getDocumentObjectType() == DocumentObjectType.Text_Range) {
                            TextRange textRange = (TextRange) obj;
                            if (textRange.getDocumentObjectType() == DocumentObjectType.Text_Range) {
                                if(org.apache.commons.lang3.StringUtils.isNotBlank((textRange.getText()))&&textRange.getText().length()>1&&!str.contains(textRange.getText().substring(0,1))){
                                    paragraph.getFormat().setFirstLineIndent(32);
                                }
                                textRange.getCharacterFormat().setFontName("方正仿宋_GBK");
                                textRange.getCharacterFormat().setFontSize(16);
                            }
                        }
                    }
                }
            }
        }
        //通过域代码添加目录表
        doc.saveToFile("C:\\Users\\fll\\Desktop\\日常工作\\测试.docx", FileFormat.Docx_2013);
//        removeSpireWarning("D:\\测试.docx");
        doc.dispose();
    }
}